﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Controller.Utils
{
    public class ByteUtils
    {

        /// <summary>
        /// 字节数据转16进制字符串
        /// </summary>
        /// <param name="iDatas">字节数据</param>
        /// <param name="iStartIndex">起始位置</param>
        /// <param name="iLength">长度</param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] iDatas, int iStartIndex, int iLength)
        {
            if (iDatas.Length < iLength + iStartIndex) iLength = iDatas.Length - iStartIndex;
            if (iLength <= 0) return "";
            //byte[] temp = new byte[iLength];
            //Array.Copy(iDatas, iStartIndex, temp, 0, iLength);
            return ByteArrayToHexString(iDatas.Skip(iStartIndex).Take(iLength).ToArray());
        }

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="iDatas"></param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] iDatas)
        {
            if (iDatas == null) return "";
            string msg = "[HEX] ";
            foreach (byte data in iDatas)
            {
                msg += $"{String.Format("0x{0:x2}", data)} ";
            }
            msg += ";";
            return msg;
        }

        /// <summary>
        /// ASCII字节数组转int
        /// </summary>
        /// <param name="iDatas"></param>
        /// <param name="iStartIndex"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public static int AsciiByteArrayToInt(byte[] iDatas, int iStartIndex, int iLength)
        {
            try
            {
                return int.Parse(ASCIIEncoding.ASCII.GetString(iDatas, iStartIndex, iLength));
            }
            catch 
            {
                return -1;
            }
        }

        /// <summary>
        /// 二进制字符串转字节数组,前补零
        /// </summary>
        /// <param name="iBinStr"></param>
        /// <returns></returns>
        public static byte[] BinStrToBytes(string iBinStr) {
            // 0011 -> 0000 0011
            int len = iBinStr.Length / 8 + (iBinStr.Length % 8 == 0 ? 0 : 1);
            byte[] result = new byte[len];
            int index = 0;
            for (int i = 0; i < len; i++) {
                int j = 0;
                if (i == 0 && len * 8 > iBinStr.Length) j = len * 8 - iBinStr.Length;
                for (; j < 8; j++) {
                    if (iBinStr[index++] == '0') continue;
                    result[i] = (byte) (result[i] | (0x01 << (7 - j)));
                }
            }
            return result;
        }

        /// <summary>
        /// 字节数组转ASCII字符串
        /// </summary>
        /// <param name="iDatas"></param>
        /// <returns></returns>
        public static string ByteArrayToAsciiString(byte[] iDatas)
        {
            if (iDatas == null) return "";
            return $"[ASCII]({iDatas[0]}){ Encoding.ASCII.GetString(iDatas, 1, iDatas.Length - 2)}({iDatas[iDatas.Length - 1]}); ";
        }

        /// <summary>
		/// 字节数组转ASCII字符串
		/// </summary>
		/// <param name="iDatas"></param>
		/// <returns></returns>
		public static string ByteArrayToAioiAsciiString(byte[] iDatas)
        {
            if (iDatas == null) return "";
            StringBuilder builder = new StringBuilder($"[ASCII]({iDatas[0]})");
            string temp = Encoding.ASCII.GetString(iDatas, 1, iDatas.Length - 2);
            int len = 0;
            if (temp.Contains("m"))
            {
                builder.Append(temp.Substring(0, temp.IndexOf("m")));
                temp = temp.Substring(temp.IndexOf("m"));
                builder.Append(GetAioiModeArray(temp, "m1", ref len));
                builder.Append(GetAioiModeArray(temp, "m2", ref len));
                builder.Append(GetAioiModeArray(temp, "m3", ref len));
                builder.Append(GetAioiModeArray(temp, "m4", ref len));
                builder.Append(GetAioiModeArray(temp, "m8", ref len));
            } 
            builder.Append(temp.Substring(len));
            builder.Append($"({iDatas[iDatas.Length - 1]});");

            return builder.ToString();
        }

        /// <summary>
        /// 获取爱鸥模式组合
        /// </summary>
        /// <param name="iSource"></param>
        /// <param name="iType"></param>
        /// <returns></returns>
        private static string GetAioiModeArray(string iSource, string iType, ref int iSkipLen)
        {
            string res = "";
            if (iSource.Contains(iType))
            {
                res = iType;
                int pos = iSource.IndexOf(iType) + iType.Length;
                iSource = iSource.Substring(pos);

                int len = 3;
                if ("m4".Equals(iType)) len = 1;
                if ("m8".Equals(iType)) len = 2;
                for (int i = 0; i < len; i++)
                {
                    res += String.Format("${0:X2}", (byte)iSource[i]);
                }
                iSkipLen = pos + len;
            }
            return res;
        }
        
        /// <summary>
        /// 字符串转字节数组(len[byte]+字节数组)
        /// </summary>
        /// <param name="iData"></param>
        /// <returns></returns>
        public static byte[] StringToUtf8ByteArray(string iData) {
            if (string.IsNullOrEmpty(iData)) {
                return new byte[1] { 0x00 };
            }
            List<byte> result = new List<byte>();
            byte[] temp = Encoding.UTF8.GetBytes(iData);
            result.Add((byte)(temp.Length > byte.MaxValue ? byte.MaxValue : temp.Length));
            result.AddRange(temp.Take(result[0]).ToArray());
            return result.ToArray();
        }

        /// <summary>
        /// 字节数组转UTF-8字符串(len[byte]+字节数组)
        /// </summary>
        /// <param name="iDatas"></param>
        /// <param name="iStartPos"></param>
        /// <returns></returns>
        public static string ByteArrayToUtf8String(byte[] iDatas, ref  int iStartPos)
        {
            // 字节数组只有一个字符 或 长度为0
            if (iDatas.Length - iStartPos < 2 || iDatas[iStartPos] == 0x00) {
                iStartPos++;
                return "";
            }
            string result = Encoding.UTF8.GetString(iDatas.Skip(iStartPos + 1).Take(iDatas[iStartPos]).ToArray());
            iStartPos += iDatas[iStartPos] + 1;
            return result;
        }
    
        
    }
}
